/**
 * =====================================================================================
 *
 *      @file:  expression.c
 *
 *    	@brief:  表达式处理，回调函数的定义
 *
 *      @version:  1.0
 *      Created:  2010年04月13日 11时53分02秒
 *      Revision:  none
 *      Compiler:  gcc -Wall -Wextra expression.c
 *
 *      @author:  easyeagel (LiuGuangBao), easyeagel@gmx.com
 *      Company:  简单C++ - www.easycpp.org
 *
 * =====================================================================================
 */

#define M_expression_implement
#include<assert.h>
#include<stdlib.h>
#include<stdio.h>
#include"base.hpp"
#include"expression.hpp"
#include"config.hpp"

typedef struct filed_info_t
{
	const char* name;
	value_t type;
	void* value;
}filed_info_t;

static const char* ftoa(double v)
{
	char* ret=(char*)malloc(24);
	assert(ret);

	snprintf(ret, 24, "%f", v);
	return ret;
}

static const char* itoa(int v)
{
	char* ret=(char*)malloc(24);
	assert(ret);

	snprintf(ret, 24, "%d", v);
	return ret;
}

static void string_op(RLTexpression_t* exp, void* data);
static void int_op(RLTexpression_t* exp, void* data);
static void double_op(RLTexpression_t* exp, void* data);

static void add_op(RLTexpression_t* exp, void* data);
static void sub_op(RLTexpression_t* exp, void* data);
static void multi_op(RLTexpression_t* exp, void* data);
static void div_op(RLTexpression_t* exp, void* data);

static void and_op(RLTexpression_t* exp, void* data);
static void not_op(RLTexpression_t* exp, void* data);
static void or_op(RLTexpression_t* exp, void* data);

static void not_equal_op(RLTexpression_t* exp, void* data);
static void equal_op(RLTexpression_t* exp, void* data);

static void filed_op(RLTexpression_t* exp, void* data);

static int g_year_value=2010;
static filed_info_t g_filed_test={"year", value_int, &g_year_value};

operator_t g_operator_dict[]=
{
	{value_val_opt,		int_op,			NULL,	NULL,	g_operator_dict},
	{value_val_opt,		double_op,		NULL,	NULL,	g_operator_dict},
	{value_val_opt,		string_op,		NULL,	NULL,	g_operator_dict},

	{value_two_opt,		add_op,			NULL,	NULL,	g_operator_dict},
	{value_two_opt,		sub_op,			NULL,	NULL,	g_operator_dict},
	{value_two_opt,		multi_op,		NULL,	NULL,	g_operator_dict},
	{value_two_opt,		div_op,			NULL,	NULL,	g_operator_dict},

	{value_two_opt,		and_op,			NULL,	NULL,	g_operator_dict},
	{value_two_opt,		or_op ,			NULL,	NULL,	g_operator_dict},
	{value_one_opt,		not_op,			NULL,	NULL,	g_operator_dict},

	{value_two_opt,		equal_op,		NULL,	NULL,	g_operator_dict},
	{value_two_opt,		not_equal_op,	NULL,	NULL,	g_operator_dict},

	{value_filed_opt,	filed_op,		NULL,	NULL,	&g_filed_test},

	{value_none_opt,	NULL,		NULL,	NULL,	NULL}
};

/* ========================================================== */
/* 算子回调函数 */

static void filed_op(RLTexpression_t* exp, void* data)
{
	filed_info_t* info=(filed_info_t*)data;
	switch(info->type)
	{
		case value_bool:
		{
			EXP_ivalue(exp)=*((int*)info->value);
			break;
		}
		case value_int:
		{
			EXP_ivalue(exp)=*((int*)info->value);
			break;
		}
		case value_double:
		{
			EXP_dvalue(exp)=*((double*)info->value);
			break;
		}
		case value_string:
		{
			EXP_svalue(exp)=str_dup((char*)info->value);
			break;
		}
		default:
		{
			break;
		}
	}
	EXP_type(exp)=info->type;
}

#define Macro_if_double(cpp_p_exp, cpp_p_op, cpp_p_done)\
{\
	if(0!=cpp_p_done) return;\
	RLTexpression_t* __exp__=(cpp_p_exp);\
	if(EXP_type(EXP_left(__exp__))==value_double || EXP_type(EXP_right(__exp__))==value_double)\
	{\
		double l=0;\
		double r=0;\
		switch(EXP_type(EXP_left(__exp__)))\
		{\
			case value_double:\
			{\
				l=EXP_dvalue(EXP_left(__exp__));\
				break;\
			}\
			case value_int:\
			case value_bool:\
			{\
				l=EXP_ivalue(EXP_left(__exp__));\
				break;\
			}\
			case value_string:\
			{\
				l=atof(EXP_svalue(EXP_left(__exp__)));\
				break;\
			}\
			default:\
			{\
				break;\
			}\
		}\
		switch(EXP_type(EXP_right(__exp__)))\
		{\
			case value_double:\
			{\
				r=EXP_dvalue(EXP_right(__exp__));\
				break;\
			}\
			case value_int:\
			case value_bool:\
			{\
				r=EXP_ivalue(EXP_right(__exp__));\
				break;\
			}\
			case value_string:\
			{\
				r=atof(EXP_svalue(EXP_right(__exp__)));\
				break;\
			}\
			default:\
			{\
				r=0;\
				break;\
			}\
		}\
\
		EXP_type(__exp__)=value_double;\
		EXP_dvalue(__exp__)=l cpp_p_op r;\
		cpp_p_done=1;\
	}\
}

#define Macro_if_int(cpp_p_exp, cpp_p_op, cpp_p_done)\
{\
	if(0!=cpp_p_done) return;\
	RLTexpression_t* __exp__=(cpp_p_exp);\
	if(EXP_type(EXP_left(__exp__))==value_int || EXP_type(EXP_right(__exp__))==value_int\
		||EXP_type(EXP_left(__exp__))==value_bool || EXP_type(EXP_right(__exp__))==value_bool)\
	{\
		int l=0;\
		int r=0;\
		switch(EXP_type(EXP_left(__exp__)))\
		{\
			case value_double:\
			{\
				l=(int)EXP_dvalue(EXP_left(exp));\
				break;\
			}\
			case value_int:\
			case value_bool:\
			{\
				l=EXP_ivalue(EXP_left(exp));\
				break;\
			}\
			case value_string:\
			{\
				l=atoi(EXP_svalue(EXP_left(exp)));\
				break;\
			}\
			default:\
			{\
				l=0;\
				break;\
			}\
		}\
		switch(EXP_type(EXP_right(__exp__)))\
		{\
			case value_double:\
			{\
				r=(int)EXP_dvalue(EXP_right(exp));\
				break;\
			}\
			case value_int:\
			case value_bool:\
			{\
				r=EXP_ivalue(EXP_right(exp));\
				break;\
			}\
			case value_string:\
			{\
				r=atoi(EXP_svalue(EXP_right(exp)));\
				break;\
			}\
			default:\
			{\
				r=0;\
				break;\
			}\
		}\
\
		EXP_type(__exp__)=value_int;\
		EXP_ivalue(__exp__)=l cpp_p_op r;\
		cpp_p_done=1;\
	}\
}

static void not_equal_op(RLTexpression_t* exp, void* data)
{
	rlt_exp_execute(EXP_left(exp), (operator_t*)data);
	rlt_exp_execute(EXP_right(exp), (operator_t*)data);

	int done=0;

	Macro_if_double(exp, !=, done);
	Macro_if_int(exp, !=, done);

	/* 可能还存在字符串比较的结果 */
	EXP_type(exp)=value_bool;
	EXP_ivalue(exp)=(0!=strcmp(EXP_svalue(EXP_left(exp)), EXP_svalue(EXP_right(exp))));
}

static void equal_op(RLTexpression_t* exp, void* data)
{
	rlt_exp_execute(EXP_left(exp), (operator_t*)data);
	rlt_exp_execute(EXP_right(exp), (operator_t*)data);

	int done=0;

	Macro_if_double(exp, ==, done);
	Macro_if_int(exp, ==, done);

	/* 可能还存在字符串比较的结果 */
	EXP_type(exp)=value_bool;
	EXP_ivalue(exp)=(0==strcmp(EXP_svalue(EXP_left(exp)), EXP_svalue(EXP_right(exp))));
}

static void not_op(RLTexpression_t* exp, void* data)
{
	rlt_exp_execute(EXP_single(exp), (operator_t*)data);

	int value=0;
	switch(EXP_type(EXP_single(exp)))
	{
		case value_double:
		{
			value=!EXP_dvalue(EXP_single(exp));
			break;
		}
		case value_int:
		case value_bool:
		{
			value=!EXP_ivalue(EXP_single(exp));
			break;
		}
		case value_string:
		{
			value=!EXP_svalue(EXP_single(exp));
			break;
		}
		default:
		{
			break;
		}
	}

	EXP_type(exp)=value_bool;
	EXP_ivalue(exp)=value;

}

#define Macro_be_bool(cpp_p_exp, cpp_p_op, cpp_p_done)\
{\
	if(1!=cpp_p_done) return;\
	RLTexpression_t* __exp__=(cpp_p_exp);\
	int l=0;\
	int r=0;\
	switch(EXP_type(EXP_left(__exp__)))\
	{\
		case value_double:\
		{\
			l=(int)EXP_dvalue(EXP_left(exp));\
			break;\
		}\
		case value_int:\
		case value_bool:\
		{\
			l=EXP_ivalue(EXP_left(exp));\
			break;\
		}\
		case value_string:\
		{\
			const char* str=EXP_svalue(EXP_left(exp));\
			if((NULL==str) || (0==strcmp(str, "0")))\
			{\
				l=0;\
				break;\
			}\
			l=1;\
			break;\
		}\
		default:\
		{\
			l=0;\
			break;\
		}\
	}\
	switch(EXP_type(EXP_right(__exp__)))\
	{\
		case value_double:\
		{\
			r=(int)EXP_dvalue(EXP_right(exp));\
			break;\
		}\
		case value_int:\
		case value_bool:\
		{\
			r=EXP_ivalue(EXP_right(exp));\
			break;\
		}\
		case value_string:\
		{\
			const char* str=EXP_svalue(EXP_right(exp));\
			if((NULL==str) || (0==strcmp(str, "0")))\
			{\
				l=0;\
				break;\
			}\
			l=1;\
			break;\
		}\
		default:\
		{\
			r=0;\
			break;\
		}\
	}\
\
	EXP_type(__exp__)=value_bool;\
	EXP_ivalue(__exp__)=l cpp_p_op r;\
\
	cpp_p_done=1;\
}

static void or_op(RLTexpression_t* exp, void* data)
{
	rlt_exp_execute(EXP_left(exp), (operator_t*)data);
	rlt_exp_execute(EXP_right(exp), (operator_t*)data);

	int done=0;

	Macro_be_bool(exp, ||, done);
}

static void and_op(RLTexpression_t* exp, void* data)
{
	rlt_exp_execute(EXP_left(exp), (operator_t*)data);
	rlt_exp_execute(EXP_right(exp), (operator_t*)data);

	int done=0;

	Macro_be_bool(exp, &&, done);
}

#undef Macro_be_bool

static void add_op(RLTexpression_t* exp, void* data)
{
	rlt_exp_execute(EXP_left(exp), (operator_t*)data);
	rlt_exp_execute(EXP_right(exp), (operator_t*)data);

	int done=0;

	Macro_if_double(exp, +, done);
	Macro_if_int(exp, +, done);
}

static void sub_op(RLTexpression_t* exp, void* data)
{
	rlt_exp_execute(EXP_left(exp), (operator_t*)data);
	rlt_exp_execute(EXP_right(exp), (operator_t*)data);

	int done=0;

	Macro_if_double(exp, -, done);
	Macro_if_int(exp, -, done);
}

static void multi_op(RLTexpression_t* exp, void* data)
{
	rlt_exp_execute(EXP_left(exp), (operator_t*)data);
	rlt_exp_execute(EXP_right(exp), (operator_t*)data);

	int done=0;

	Macro_if_double(exp, *, done);
	Macro_if_int(exp, *, done);
}

static void div_op(RLTexpression_t* exp, void* data)
{
	rlt_exp_execute(EXP_left(exp), (operator_t*)data);
	rlt_exp_execute(EXP_right(exp), (operator_t*)data);

	int done=0;

	Macro_if_double(exp, /, done);
	Macro_if_int(exp, /, done);
}

#undef Macro_if_double
#undef Macro_if_int

static void int_op(RLTexpression_t* exp, void* data)
{
	data=0;

	switch(EXP_type(exp))
	{
		case value_double:
		{
			double t=EXP_dvalue(exp);
			EXP_ivalue(exp)=(int)t;
			break;
		}
		case value_int:
		case value_bool:
		{
			break;
		}
		case value_string:
		{
			int t=atoi(EXP_svalue(exp));
			EXP_ivalue(exp)=t;
			break;
		}
		default:
		{
			EXP_ivalue(exp)=0;
		}
	}

	EXP_type(exp)=value_int;
}

static void double_op(RLTexpression_t* exp, void* data)
{
	data=0;

	switch(EXP_type(exp))
	{
		case value_double:
		{
			break;
		}
		case value_int:
		case value_bool:
		{
			int t=EXP_ivalue(exp);
			EXP_dvalue(exp)=t;
			break;
		}
		case value_string:
		{
			double t=atof(EXP_svalue(exp));
			EXP_dvalue(exp)=t;
			break;
		}
		default:
		{
			EXP_dvalue(exp)=0;
		}
	}

	EXP_type(exp)=value_double;
}

static void string_op(RLTexpression_t* exp, void* data)
{
	data=0;

	switch(EXP_type(exp))
	{
		case value_double:
		{
			EXP_svalue(exp)=ftoa(EXP_dvalue(exp));
			break;
		}
		case value_int:
		case value_bool:
		{
			EXP_svalue(exp)=itoa(EXP_ivalue(exp));
			break;
		}
		case value_string:
		{
			break;
		}
		default:
		{
			EXP_svalue(exp)=0;
		}
	}

	EXP_type(exp)=value_string;
}


/* ====================================================== */
/* RLTexpression_t辅助函数或实用工具 */

RLTexpression_t* rlt_exp_create(size_t idx)
{
	RLTexpression_t* ret=(RLTexpression_t*)malloc(sizeof(*ret));
	assert(ret);
	memset(ret, 0, sizeof(*ret));

	ret->index=idx;

	return ret;
}

void rlt_exp_execute(RLTexpression_t* exp, operator_t* dict)
{
	operator_t* op=dict + exp->index;
	op->call(exp, op->data);
}

void rlt_exp_free(RLTexpression_t* exp, operator_t* dict)
{
	if(EXP_type(exp)==value_string)
	{
		free((void*)EXP_svalue(exp));
		EXP_type(exp)=value_none;
	}

	switch(dict[exp->index].type)
	{
		case value_one_opt:
		case value_filed_opt:
		{
			rlt_exp_free(EXP_single(exp), dict);
			return;
		}
		case value_two_opt:
		{
			rlt_exp_free(EXP_left(exp), dict);
			rlt_exp_free(EXP_right(exp), dict);
			return;
		}
		case value_three_opt:
		{
			rlt_exp_free(EXP_first(exp), dict);
			rlt_exp_free(EXP_second(exp), dict);
			rlt_exp_free(EXP_third(exp), dict);
			return;
		}
		default:
		{
			return;
		}
	}

	free(exp);
}

void rlt_exp_single(RLTexpression_t* exp, RLTexpression_t* single)
{
	EXP_single(exp)=single;
}

void rlt_exp_left(RLTexpression_t* exp, RLTexpression_t* left)
{
	EXP_left(exp)=left;
}

void rlt_exp_right(RLTexpression_t* exp, RLTexpression_t* right)
{
	EXP_right(exp)=right;
}

void rlt_exp_first(RLTexpression_t* exp, RLTexpression_t* first)
{
	EXP_first(exp)=first;
}

void rlt_exp_second(RLTexpression_t* exp, RLTexpression_t* second)
{
	EXP_second(exp)=second;
}

void rlt_exp_third(RLTexpression_t* exp, RLTexpression_t* third)
{
	EXP_third(exp)=third;
}

void rlt_exp_dvalue(RLTexpression_t* exp, double value)
{
	EXP_type(exp)=value_double;
	EXP_dvalue(exp)=value;
}

void rlt_exp_ivalue(RLTexpression_t* exp, int value)
{
	EXP_type(exp)=value_int;
	EXP_ivalue(exp)=value;
}

void rlt_exp_svalue(RLTexpression_t* exp, const char* value)
{
	EXP_type(exp)=value_string;
	EXP_svalue(exp)=value;
}

#undef M_expression_implement

